package com.googlecode.alogwe.sprockit.js;

import java.lang.reflect.InvocationTargetException;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;

public class JSConsole extends ScriptableObject {


	private static JSConsole	instance = null;
	/**
	 * The zero-parameter constructor, required by Rhino for all host objects
	 * <p>
	 * When Context.defineClass is called with this class, it will construct
	 * Console.prototype using this constructor.
	 */
	public JSConsole() {
		instance = this;
	}

	/**
	 * The Java method defining the JavaScript constructor.
	 */
	public void jsConstructor() {
	}
	
	public static JSConsole getInstance() {
		if (instance == null) {
			instance = new JSConsole();
		}
		return instance;
	}

	private static final String	JS_CLASSNAME	= "Console";

	/**
	 * Returns the name of this JavaScript class. Typically the same name as the
	 * constructor.
	 */
	@Override
	public String getClassName() {
		return JS_CLASSNAME;
	}

	/**
	 * Creates it's own JavaScript host object in the given context/scope
	 * <p>
	 * <b>TODO</b> Figure out a better way to do this.
	 * 
	 * @param cx
	 *            The Context used to create the JavaScript host object
	 * @param scope
	 *            The object in the JavaScript environment that will receive
	 *            this newly created host object
	 * @return void
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * @throws InvocationTargetException
	 */
	public static void createJsHostObject(Context cx, Scriptable scope) throws IllegalAccessException,
			InstantiationException, InvocationTargetException {
		ScriptableObject.defineClass(scope, JSConsole.class);
		Object[] args = {};
		//Scriptable console = cx.newObject(scope, JS_CLASSNAME, args);
		scope.put(JS_CLASSNAME, scope, getInstance());
	}

	/**
	 * Writes all arguments to the Console's outputs; <br>
	 * Builds a string from each argument's toString() method evaluated in the
	 * current context / scope, separated by a space;
	 * <p>
	 * Example of variable argument JavaScript binding.<br>
	 * <a href=http://mxr.mozilla.org/mozilla/source/js/rhino/examples/Foo.java>
	 * http://mxr.mozilla.org/mozilla/source/js/rhino/examples/Foo.java</a>
	 * <p>
	 * All variable arguments methods must have the same number and types of
	 * parameters, and must be static.
	 * <p>
	 * <b>TODO</b> Write to a configurable output stream instead of System.out
	 * 
	 * @param cx
	 *            the Context of the current thread
	 * @param thisObj
	 *            the JavaScript 'this' value.
	 * @param args
	 *            the array of arguments for this call
	 * @param funObj
	 *            the function object of the invoked JavaScript function This
	 *            value is useful to compute a scope using
	 *            Context.getTopLevelScope().
	 * @return void
	 * @see org.mozilla.javascript.ScriptableObject#getTopLevelScope
	 */
	public static void jsFunction_write(Context cx, Scriptable thisObj, Object[] args,
			Function funObj) {

		StringBuffer b = new StringBuffer();
		for (int i = 0, len = args.length; i < len; i++) {
			b.append(Context.toString(args[i]));
			if (i + 1 != args.length)
				b.append(" ");
		}

		System.out.println(b);
	}

}
